﻿using PengSW.XmlHelper;
using System.Xml.Linq;

namespace PengSW.Schedule
{
    /// <summary>
    /// 计划任务工厂接口定义
    ///     计划任务工厂负责创建计划任务
    ///     计划任务工厂实例会通过扫描指定程序集中的类定义来自动创建，
    ///     因此计划任务工厂必须提供缺省构造函数，因此计划任务工厂所需要的额外参数，
    ///     必须通过外部静态类才能获得。
    /// </summary>
    public interface IScheduleFactory
    {
        /// <summary>
        /// 对计划任务工厂的描述
        /// </summary>
        string Description { get; }
        /// <summary>
        /// 判断计划任务工厂是否能从指定的xml结点中获得所需要的信息来创建一个计划任务。
        /// </summary>
        /// <param name="aXElement">目标xml结点</param>
        /// <returns>如果能创建，则返回true</returns>
        bool IsCreatable(XElement aXElement);
        /// <summary>
        /// 用指定的xml结点中的信息创建一个计划任务。
        ///     在调用此方法前，应保证用IsCreatable检查过目标xml结点了。
        /// </summary>
        /// <param name="aXElement">目标xml结点</param>
        /// <returns>返回用目标xml结点中的信息创建的计划任务实例</returns>
        ISchedule CreateSchedule(XElement aXElement);
        /// <summary>
        /// 创建一个计划任务实例。
        ///     如果创建计划任务实例需要额外的信息，计划任务工厂可以在自身预先存放这些信息。
        ///     也可以通过打开一个编辑界面窗体的方式来获得所需要的信息。
        /// </summary>
        /// <returns>返回所创建的计划任务实例，如果创建失败，应抛出异常。</returns>
        ISchedule CreateSchedule();
    }

    public abstract class NormalScheduleFactory<T> : IScheduleFactory where T : ISchedule, new()
    {
        public abstract string Description { get; }

        public ISchedule CreateSchedule()
        {
            return new T { Description = Description };
        }

        public ISchedule CreateSchedule(XElement aXElement)
        {
            T aSchedule = new T();
            aSchedule.ReadFromXml(aXElement);
            return aSchedule;
        }

        public bool IsCreatable(XElement aXElement) => aXElement?.GetAttributeValue("Type", null) == typeof(T).Name;
    }
}
